const request = require('request');
const http = require('http');
import {querystring} from 'cess-core';

const unparsed = require('koa-body/unparsed.js');

var fs = require('fs');

var defaultConfig = {
	changeOrigin: false,
	ws: true
}

export default function proxy(config){

	//花括号叫目标对象，后面的obj、obj1是源对象。
	//对象合并是指：将源对象里面的属性添加到目标对象中去，若两者的属性名有冲突，后面的将会覆盖前面的
	var config = Object.assign({},defaultConfig,config);
	var proxyUrl = config.target;
	var defaultOptions = config.defaultOptions;
	//去掉代理 url 后面的反斜杠 /
	if(proxyUrl && proxyUrl.endsWith("/")){
		proxyUrl = proxyUrl.substr(0,proxyUrl.length - 1)
	}

	//实现 host 路由
	var rewritePath = function(ctx){

		//如果没有设置 pathRewrite，则对 url 不做任何处理
		if(!config.pathRewrite){
			return ctx.path
		}

		//如果 pathRewrite 是一个函数，则函数的返回值做为代理请求 url
		if(typeof config.pathRewrite == 'function'){
			return config.pathRewrite(ctx)
		}

		//如果 pathRewrite 是一个对象
		for(var item in config.pathRewrite){
			var regexp = RegExp(item,"i")

			if(regexp.test(ctx.path)){
				return ctx.path.replace(regexp,config.pathRewrite[item])
			}
		}

		return ctx.path
	}

	var rewriteHeader = function(ctx){

		//如果没有设置 pathRewrite，则对 url 不做任何处理
		if(!config.rewriteHeader){
			return
		}

		//如果 pathRewrite 是一个函数，则函数的返回值做为代理请求 url
		if(typeof config.rewriteHeader == 'function'){
			return config.rewriteHeader(ctx)
		}

		return config.rewriteHeader;
	}


	//拼接 url
	var conurl = (url) => {
		if(url.startsWith("/")){
			return proxyUrl + url;
		}

		return proxyUrl + '/' + url;
	}

	var processBoby = function (ctx) {


        if(ctx.request.headers['content-type'] == 'application/json'){
			//如果是 application/json 请求体
			return JSON.stringify(ctx.request.body);
		}

		if ((ctx.request.method === "POST" || ctx.request.method === "post") && ctx.request.headers['content-type'] != "multipart/form-data"){
			return ctx.request.body[unparsed] || querystring.stringify(ctx.request.body);
		}

		return querystring.stringify(ctx.request.body);
	}
	return async (ctx, next) => {

		var options = Object.assign({}, defaultOptions);
		//设置请求 url
		options.url = conurl(rewritePath(ctx))


		var body = processBoby(ctx);


		var query = querystring.stringify(ctx.request.query);

		if (query) {
			options.url += (options.url.indexOf('?') === -1 ? '?' : '&') + query
		}

		//设置请求消息体
		options.body = body;


		if(ctx.request.files){

			var form = {};

			for(var name in ctx.request.body){
				form[name] = ctx.request.body[name];
			}

			for(var name in ctx.request.files){
				var file = ctx.request.files[name];
				var stream = fs.createReadStream(file.path);
				// var states = fs.statSync(file.path);

				form[name] = {
					value: stream,
					options: {
						filename: file.name
					}
				}
			}
			options.formData = form;
		}
		//请求头信息
		options.headers = {};

		options.method = ctx.request.method

		//处理请求头
		for(var item in ctx.request.headers){
			if((item == 'host' || item == 'origin') && config.changeOrigin){
				continue
			}
			if(item == 'connection'
				|| item == 'content-length'){
				continue;
			}
			options.headers[item] = ctx.request.headers[item];
			//console.log(item+":"+ctx.request.headers[item])
		}//'multipart/form-data; boundary=----WebKitFormBoundarydZcGwyrFyw8fTuzu'

		if(ctx.request.files){
			options.headers['content-type'] = 'multipart/form-data';
		}

		//处理自定认请求头
		var rheaders = rewriteHeader(ctx);

		if(rheaders){
			//如果有自定义请求头
			options.headers = Object.assign({},options.headers,rheaders)
		}

		var callback = function(resolve, reject, error, response, body) {

			// if (!error && response.statusCode == 200) {
			if(response){
				//如果有响应信息，则把相应的信息返回的前端

				//设置响应头信息
				for(var item in response.headers){
					ctx.set(item, response.headers[item]);
				}

				//设置返回的状态信息
				ctx.response.status = response.statusCode
				ctx.response.statusText = response.statusMessage
			}

			resolve();
		}

		return new Promise(function(resolve, reject) {
			// request(options, (error, response, body) => {
			// 	callback(resolve, reject, error, response, body)
			// }).encoding = null;//encoding设为 null 后
			// let x = request(options, (error, response, body) => {
			// 	callback(resolve, reject, error, response, body)
			// });


			let x = request(options,  (error, response, body) => {
				callback(resolve, reject, error, response, body)
			});
			//response
			// x.on('response',function (response) {
			// 	console.log(response)
			// });

			//把响应流直接输入到 koa 输出流，提高性能，并且能兼容各种格式的数据
			x.pipe(ctx.res)

		});
	}
}
